/*
 * Galaxium Messenger
 * Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Text;

using GLib;
using Gdk;
using Gtk;

using Anculus.Core;

using Galaxium.Core;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

namespace Galaxium.Protocol.Msn.GtkGui
{
	public class MsnContactTreeManager : BasicContactTreeManager
	{
		public override void RenderText (object data, CellRendererContact renderer)
		{
			if (!(data is MsnContact))
			{
				base.RenderText (data, renderer);
				return;
			}
			
			MsnContact contact = data as MsnContact;
			StringBuilder sb = new StringBuilder ();
			ContactTreeDetailLevel detail = contact.Session.Account.DetailLevel;
			IConfigurationSection config = Configuration.ContactList.Section;
			
			if (contact.Session.Account.UseDefaultListView)
			{
				detail = (ContactTreeDetailLevel)config.GetInt (Configuration.ContactList.DetailLevel.Name, Configuration.ContactList.DetailLevel.Default);
			}
			
			sb.Append (Markup.EscapeText (contact.DisplayIdentifier));
			
			if (detail != ContactTreeDetailLevel.Compact)
			{
				sb.AppendFormat ("<span foreground=\"#505050\" weight=\"light\"><i> ({0})</i></span>\n", contact.Presence.State);
			
				if (detail == ContactTreeDetailLevel.Detailed)
					sb.AppendFormat ("<span size=\"small\">{0}</span>\n", Markup.EscapeText (contact.UniqueIdentifier));
			}
			
			if ((!contact.CurrentMedia.Enabled) || string.IsNullOrEmpty (contact.CurrentMedia.Display))
			{
				sb.Append ("<span foreground=\"#505050\" weight=\"light\" size=\"smaller\">");
				
				if (detail == ContactTreeDetailLevel.Compact)
					sb.Append (" ");
				
				bool showPersonalMessages = contact.Session.Account.UseDefaultListView ? config.GetBool (Configuration.ContactList.ShowContactMessages.Name, Configuration.ContactList.ShowContactMessages.Default) : contact.Session.Account.ShowPersonalMessages;
				
				if (showPersonalMessages && contact.DisplayMessage != null && contact.DisplayMessage.Length > 0)
					sb.Append (Markup.EscapeText (contact.DisplayMessage));
				else
					sb.Append ("No personal message.");
				
				sb.Append ("</span>");
			}
			else
			{
				string emot = string.Empty;
				
				if (EmoticonUtility.ActiveSet != null)
				{
					if (contact.CurrentMedia.Type == MsnCurrentMediaType.Music)
						emot = "(8)";
					else if (contact.CurrentMedia.Type == MsnCurrentMediaType.Games)
						emot = "(xx)";
					else if (contact.CurrentMedia.Type == MsnCurrentMediaType.Office)
						emot = "(co)";
				}
				
				sb.Append ("<span foreground=\"#505050\" weight=\"light\" size=\"smaller\">");
				sb.Append (Markup.EscapeText (emot + contact.CurrentMedia.Display + emot));
				sb.Append ("</span>");
			}
			
			if (detail == ContactTreeDetailLevel.Compact)
				sb.AppendFormat (" <span foreground=\"#505050\" weight=\"light\"><i>({0})</i></span>\n", contact.Presence.State);
			
			renderer.ShowEmoticons = true;
			renderer.Markup = sb.ToString ();
		}
		
		public override void RenderLeftImage (object data, CellRendererPixbuf renderer)
		{
			if (!(data is MsnContact))
			{
				base.RenderLeftImage (data, renderer);
				return;
			}
			
			IConfigurationSection config = Configuration.ContactList.Section;
			MsnContact contact = data as MsnContact;
			ContactTreeDetailLevel detailLevel = contact.Session.Account.DetailLevel;
			
			if (contact.Session.Account.UseDefaultListView)
			{
				detailLevel = (ContactTreeDetailLevel)config.GetInt (Configuration.ContactList.DetailLevel.Name, Configuration.ContactList.DetailLevel.Default);
			}
			
			IIconSize iconSize = IconSizes.Other;
			Pixbuf pixbuf = null;
			
			switch (detailLevel)
			{
			case ContactTreeDetailLevel.Compact:
				iconSize = IconSizes.Small;
				break;
				
			case ContactTreeDetailLevel.Normal:
				iconSize = IconSizes.Medium;
				break;
				
			case ContactTreeDetailLevel.Detailed:
				iconSize = IconSizes.Large;
				break;
				
			default:
				// not currently dealign with this size.
				break;
			}
			
			bool showDisplayImages = contact.Session.Account.UseDefaultListView ? config.GetBool (Configuration.ContactList.ShowContactImages.Name, Configuration.ContactList.ShowContactImages.Default) : contact.Session.Account.ShowDisplayImages;
			
			if (contact.DisplayImage != null && contact.DisplayImage.ImageBuffer != null && showDisplayImages && !contact.SupressImage)
			{
				try
				{
					if (contact.Presence == MsnPresence.Idle)
						pixbuf = PixbufUtility.GetShadedPixbuf(new Gdk.Pixbuf(contact.DisplayImage.ImageBuffer), detailLevel);
					else if (contact.Presence == MsnPresence.Offline)
						pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
					else
						pixbuf = PixbufUtility.GetFramedPixbuf (new Gdk.Pixbuf(contact.DisplayImage.ImageBuffer), detailLevel);
				}
				catch
				{
					if (contact.Presence == MsnPresence.Idle)
						pixbuf = IconUtility.GetIcon ("galaxium-idle", iconSize);
					else if (contact.Presence == MsnPresence.Offline)
						pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
					else
						pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
				}
			}
			else
			{
				if (contact.Presence == MsnPresence.Idle)
					pixbuf = IconUtility.GetIcon ("galaxium-idle", iconSize);
				else if (contact.Presence == MsnPresence.Offline)
					pixbuf = IconUtility.GetIcon ("galaxium-offline", iconSize);
				else
					pixbuf = IconUtility.GetIcon ("galaxium-online", iconSize);
			}
			
			// We are not in compact mode, so we need to use overlays now.
			if (detailLevel != ContactTreeDetailLevel.Compact)
			{
				if (contact.IsBlocked)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-block", IconSizes.Small));
				else if (contact.Presence == MsnPresence.Away)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-away", IconSizes.Small));
				else if (contact.Presence == MsnPresence.Brb)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-brb", IconSizes.Small));
				else if (contact.Presence == MsnPresence.Busy)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-busy", IconSizes.Small));
				else if (contact.Presence == MsnPresence.Lunch)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-lunch", IconSizes.Small));
				else if (contact.Presence == MsnPresence.Phone)
					pixbuf = PixbufUtility.GetOverlayedRightPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-phone", IconSizes.Small));
				
				if (!contact.IsInList(MsnListType.Reverse))
					pixbuf = PixbufUtility.GetOverlayedLeftPixbuf (pixbuf, IconUtility.GetIcon ("galaxium-status-reverse", IconSizes.Small));
			}
			
			renderer.Pixbuf = pixbuf;
			renderer.Width = pixbuf.Width;
			renderer.Visible = true;
		}
		
		public override InfoTooltip GetTooltip (object data)
		{
			if (data is MsnContact)
				return new ContactListTooltip (data as MsnContact);
			
			return base.GetTooltip (data);
		}
		
		public override int Compare (object data1, object data2)
		{
			if ((data1 is ContactTreeRealGroup) && !(data2 is ContactTreeOfflineVirtualGroup))
			{
				MsnGroup group = (data1 as ContactTreeRealGroup).Group as MsnGroup;
				
				// Handle the "Other Contacts" group
				if (group.UniqueIdentifier == "0")
					return (Tree.SortOrder == SortOrder.Ascending) ? int.MaxValue : int.MinValue;
			}
			if ((data2 is ContactTreeRealGroup) && !(data1 is ContactTreeOfflineVirtualGroup))
			{
				MsnGroup group = (data2 as ContactTreeRealGroup).Group as MsnGroup;
				
				// Handle the "Other Contacts" group
				if (group.UniqueIdentifier == "0")
					return (Tree.SortOrder == SortOrder.Ascending) ? int.MinValue : int.MaxValue;
			}
			
			bool sortAlphabet = Session.Account.SortAlphabetic;
			
			if (Session.Account.UseDefaultListView)
				sortAlphabet = Configuration.ContactList.Section.GetBool (Configuration.ContactList.SortAlphabetic.Name, Configuration.ContactList.SortAlphabetic.Default);
			
			MsnContact contact1 = data1 as MsnContact;
			
			if ((contact1 != null) && (!sortAlphabet))
			{
				MsnContact contact2 = data2 as MsnContact;
				
				int ret = GetPresenceValue (contact1.Presence).CompareTo (GetPresenceValue (contact2.Presence));
				
				if (ret != 0)
					return ret;
			}
			
			return base.Compare (data1, data2);
		}
		
		private int GetPresenceValue (IPresence presence)
		{
			if (presence == MsnPresence.Online)
				return 0;
			else if (presence == MsnPresence.Idle)
				return 1;
			else if (presence == MsnPresence.Phone)
				return 2;
			else if (presence == MsnPresence.Brb)
				return 3;
			else if (presence == MsnPresence.Busy)
				return 4;
			else if (presence == MsnPresence.Lunch)
				return 5;
			else if (presence == MsnPresence.Away)
				return 6;
			else if (presence == MsnPresence.Invisible)
				return 7;
			else
				return 8;
		}
	}
}
